<?php
/**
 * Users manager - a system module.
 *
 * @author Martin "DevelX" Jurča
 */
class Users extends Module {
    protected $name = 'Users';
    protected $administrable = true;
    protected $version = '2009-10-25';
    protected $system = true;
    protected $details = array('dependencies' => array(),
            'observes' => array('Users'));

    const GROUPS_TABLE = 'usersGroups';
    const USERS_TABLE = 'usersUsers';
    const USERS_IN_GROUP_TABLE = 'usersUsersInGroup';
    const GROUP_RIGHTS_TABLE = 'usersGroupRights';
    const USER_RIGHTS_TABLE = 'usersUserRights';
    const USER_REVOKED_RIGHTS_TABLE = 'usersUserRevokedRights';
    const RIGHTS_TABLE = 'usersRights';
    const DEFAULT_REQUIRE = '_assign user rights';

    private $groupsTable = array('id' => 'iNP+', 'name' => "v'255'NU",
            'require' => 's');
    private $usersTable = array('id' => 'iP+', 'login' => "v'255'NU",
            'password' => 'sN', 'photo' => 'i', 'name' => 's', 'surname' =>
            's', 'email' => 's', 'www' => 's', 'active' => 'iN',
            'registered' => 'iN', 'lastLogin' => 'i');
    private $usersInGroupTable = array('user' => 'iNI', 'group' => 'iNI');
    private $groupRightsTable = array('group' => 'iNI', 'module' => "v'255'NI",
            'right' => "v'255'NI");
    private $userRightsTable = array('user' => 'iNI', 'module' => "v'255'NI",
            'right' => "v'255'NI");
    private $userRevokedRightsTable = array('user' => 'iNI', 'module' =>
            "v'255'NI", 'right' => "v'255'NI");
    private $rightsTable = array('module' => "v'255'NI", 'id' => "v'255'NI",
            'requires' => "v'255'NI");

    private $groupsRecord = array('table' => self::GROUPS_TABLE, 'data' =>
            array());
    private $usersRecord = array('table' => self::USERS_TABLE, 'data' =>
            array());
    private $usersInGroupRecord = array('table' => self::USERS_IN_GROUP_TABLE,
            'data' => array());
    private $groupRightsRecord = array('table' => self::GROUP_RIGHTS_TABLE,
            'data' => array());
    private $userRightsRecord = array('table' => self::USER_RIGHTS_TABLE,
            'data' => array());
    private $userRevokedRecord = array('table' =>
            self::USER_REVOKED_RIGHTS_TABLE, 'data' => array());
    private $rightsRecord = array('table' => self::RIGHTS_TABLE, 'data' =>
            array());

    private $logoutTimeout = 1200;
    private $loginTimeout = 120;

    public function __construct(DBAPI $dbapi, RecordList $recordList) {
        parent::__construct($dbapi, $recordList);
        $this->groupsRecord['properties'] = $this->groupsTable;
        $this->usersRecord['properties'] = $this->usersTable;
        $this->usersInGroupRecord['properties'] = $this->usersInGroupTable;
        $this->groupRightsRecord['properties'] = $this->groupRightsTable;
        $this->userRightsRecord['properties'] = $this->userRightsTable;
        $this->userRevokedRecord['properties'] = $this->userRevokedRightsTable;
        $this->rightsRecord['properties'] = $this->rightsTable;
        $this->usersInGroupRecord['properties']['users'] = array('linkBy' =>
                'id', 'linkTo' => 'user', 'linkOp' => '=', 'record' =>
                $this->usersRecord);
        if (isset($_SESSION['user']) && ($_SESSION['user'] != null)) {
            if (!isset($_SESSION['user']['data']['lastActive'])) {
                $_SESSION['user']['data']['lastActive'] = time();
            }
            if ($_SESSION['user']['data']['lastActive'] < time() -
                    $this->logoutTimeout) {
                $_SESSION['user'] = null;
            }
            if (isset($_SESSION['user']) && ($_SESSION['user'] != null)) {
                $_SESSION['user']['data']['lastActive'] = time();
            }
        }
    }

    public function install() {
        $this->dbdriver->createTable(self::GROUPS_TABLE, $this->groupsTable);
        $this->dbdriver->createTable(self::USERS_TABLE, $this->usersTable);
        $this->dbdriver->createTable(self::USERS_IN_GROUP_TABLE,
                $this->usersInGroupTable);
        $this->dbdriver->createTable(self::GROUP_RIGHTS_TABLE,
                $this->groupRightsTable);
        $this->dbdriver->createTable(self::USER_RIGHTS_TABLE,
                $this->userRightsTable);
        $this->dbdriver->createTable(self::USER_REVOKED_RIGHTS_TABLE,
                $this->userRevokedRightsTable);
        $this->dbdriver->createTable(self::RIGHTS_TABLE, $this->rightsTable);

        $root = $this->usersRecord;
        $root['data'] = array('login' => 'root', 'password' => sha1('root'),
                'active' => 1, 'registered' => time());
        $this->dbapi->save($root);
        $guest = $this->usersRecord;
        $guest['data'] = array('login' => '<guest>', 'password' => sha1(''),
                'active' => 1, 'registered' => time());
        $this->dbapi->save($guest);
        $guestGroup = $this->groupsRecord;
        $guestGroup['data'] = array('name' => '<guest>', 'require' =>
                'Users-_assign guest rights');
        $this->dbapi->save($guestGroup);

        $this->registerRights($this->getName(), $this->getRights());
        
        return true;
    }

    public function uninstall() {
        $this->dbdriver->dropTable(self::GROUPS_TABLE);
        $this->dbdriver->dropTable(self::USERS_TABLE);
        $this->dbdriver->dropTable(self::USERS_IN_GROUP_TABLE);
        $this->dbdriver->dropTable(self::GROUP_RIGHTS_TABLE);
        $this->dbdriver->dropTable(self::USER_RIGHTS_TABLE);
        $this->dbdriver->dropTable(self::USER_REVOKED_RIGHTS_TABLE);
        $this->dbdriver->dropTable(self::USER_RIGHTS_TABLE);
        return true;
    }

    public function initDisplay($param = null) {
        $this->setAccessErrorMsgs();
        if ((Kernel::getMode() == Kernel::ADMIN) &&
                !$this->hasRights('_view admin')) {
            Modules::getModule('View')->addJS(Config::WEB_DIR .
                    $this->getDir('/sha1.js', true));
            Modules::getModule('View')->addJS(Config::WEB_DIR .
                    $this->getDir('/login.js', true));
        }
    }

    public function display($param = null) {
        if (Kernel::getMode() == Kernel::ADMIN) {
            $this->displayAdmin($param);
        }
    }

    public function registerRights($module, $rights) {
        $record = $this->rightsRecord;
        foreach ($rights as $right) {
            if (is_array($right)) {
                $check = &$this->dbapi->load($this->rightsRecord,
                        '`module` = \'' . $this->dbdriver->
                        escapeString($module) . '\' AND `id` = \'' .
                        $this->dbdriver->escapeString($right['id']) . '\'');
            } else {
                $check = &$this->dbapi->load($this->rightsRecord,
                        '`module` = \'' . $this->dbdriver->
                        escapeString($module) . '\' AND `id` = \'' .
                        $this->dbdriver->escapeString($right) . '\'');
            }
            if (count($check) > 0) {
                continue;
            }
            if (is_array($right)) {
                $record['data'] = array('module' => $module, 'id' =>
                        $right['id'], 'requires' => $right['req']);
            } else {
                $record['data'] = array('module' => $module, 'id' => $right,
                        'requires' => self::DEFAULT_REQUIRE);
            }
            $this->dbapi->save($record);
        }
    }
    
    public function getIdOfUserName($login) {
        $cols = array('id');
        $id = &$this->dbdriver->select(self::USERS_TABLE, $cols,
                '`login` = \'' . $this->dbdriver->escapeString($login) . '\'');
        return isset($id[0]) ? $id[0]['id'] : 0;
    }

    public function checkRights($module, $id) {
        $check = &$this->dbapi->load($this->rightsRecord, '`module` = \'' .
                $this->dbdriver->escapeString($module) . '\' AND `id` = \'' .
                $this->dbdriver->escapeString($id) . '\'');
        if (count($check) == 0) {
            trigger_error("trying to check for unexisting user right: " .
                    "$module-$id", E_USER_WARNING);
            return false;
        }
        $user = &$this->getUser();
        if ($user['data']['login'] == 'root') {
            return true;
        }
        $userRights = &$this->dbapi->load($this->userRightsRecord,
                '`module` = \'' . $this->dbdriver->escapeString($module) .
                '\' AND `right` = \'' . $this->dbdriver->escapeString($id) .
                '\' AND `user` = ' . $user['data']['id']);
        if (count($userRights) > 0) {
            return true;
        }
        $revoked = &$this->dbapi->load($this->userRevokedRecord,
                '`user` = ' . $user['data']['id'] . ' AND `module` = \'' .
                $this->dbdriver->escapeString($module) .
                '\' AND `right` = \'' . $this->dbdriver->escapeString($id) .
                '\'');
        if (count($revoked) > 0) {
            return false;
        }
        $userGroups = &$this->dbapi->load($this->usersInGroupRecord,
                '`user` = ' . $user['data']['id']);
        foreach ($userGroups as $group) {
            $rights = &$this->dbapi->load($this->groupRightsRecord,
                    '`group` = ' . (int) $group['data']['group'] .
                    ' AND `module` = \'' .
                    $this->dbdriver->escapeString($module) . '\' AND `right`' .
                    ' = \'' . $this->dbdriver->escapeString($id) . '\'');
            if (count($rights) > 0) {
                return true;
            }
        }
        $guestGroup = &$this->dbapi->load($this->groupsRecord,
                "`name` = '<guest>'");
        $rights = &$this->dbapi->load($this->groupRightsRecord, '`group` = ' .
                (int) $guestGroup[0]['data']['id'] . ' AND `module` = \'' .
                $this->dbdriver->escapeString($module) . '\' AND `right` = ' .
                '\'' . $this->dbdriver->escapeString($id) . '\'');
        return count($rights) > 0;
    }

    public function loginUser() {
        if (isset($_POST['sendTimestamp'])) {
            $this->safeLoginUser();
            return;
        }
        $user = &$this->dbapi->load($this->usersRecord, '`login` = \'' .
                $this->dbdriver->escapeString($_POST['login']) . '\' AND ' .
                '`password` = \'' . sha1($_POST['password']) . '\' AND ' .
                '`active` > 0');
        if (count($user) > 0) {
            $user[0]['data']['lastLogin'] = time();
            $this->dbapi->update($user[0]);
            $_SESSION['user'] = $user[0];
        }
    }

    public function &getUser($id = null) {
        if (is_numeric($id)) {
            $user = $this->usersRecord;
            $user['data']['id'] = (int) $id;
            $this->dbapi->refresh($user);
            return $user;
        } else {
            if (isset($_SESSION['user']) && ($_SESSION['user'] != null)) {
                return $_SESSION['user'];
            }
            $guest = &$this->dbapi->load($this->usersRecord,
                    '`login` = \'<guest>\'');
            return $guest[0];
        }
    }

    public function &getUsers() {
        $param = array();
        $users = $this->recordList->getList($this->usersRecord, $param);
        foreach ($users as &$user) {
            $user['password'] = '';
        }
        return $users;
    }

    public function getBlankUserRecord() {
        return $this->usersRecord;
    }

    public function &onLogin(&$details, $source) {
        $this->loginUser();
        $result = isset($_SESSION['user']);
        if ($result) {
            Modules::getModule('View')->addMessage($this->lang('loginSuccess'),
                    View::MSG_CONFIRM);
            $user = $_SESSION['user'];
            $user['data'][2] = '';
            $user['data']['password'] = '';
            Modules::fireEvent('userLoggedIn', $user, 'Users');
        } else {
            Modules::getModule('View')->addMessage($this->lang('loginFailed'),
                    View::MSG_ERROR);
        }
        $details['password'] = null;
        return $result;
    }

    public function &onLogout(&$details, $source) {
        $_SESSION['user'] = null;
        $result = $_SESSION['user'] == null;
        if ($result) {
            Modules::getModule('View')->addMessage(
                    $this->lang('logoutSuccess'), View::MSG_CONFIRM);
        } else {
            Modules::getModule('View')->addMessage($this->lang('logoutFailed'),
                    View::MSG_ERROR);
        }
        Kernel::setRedirect(Config::WEB_DIR . (isset($_GET['inAdmin']) ||
                isset($_POST['inAdmin']) ? '/admin/' : '/'));
        return $result;
    }

    public function &onDeleteGroup(&$details, $source) {
        $result = null;
        Kernel::setRedirect($this->getLink('groups/'));
        if (!$this->hasRights('delete groups')) {
            Modules::getModule('View')->addMessage(
                    $this->lang('notSufficentRights'), View::MSG_ERROR);
            return $result;
        }
        $id = (int) substr($details, 0, -1);
        $this->dbdriver->delete(self::USERS_IN_GROUP_TABLE, '`group` = ' .
                $id);
        $this->dbdriver->delete(self::GROUP_RIGHTS_TABLE, '`group` = ' . $id);
        $this->dbdriver->delete(self::GROUPS_TABLE, '`id` = ' . $id);
        return $result;
    }

    public function &onDeleteUser(&$details, $source) {
        $result = null;
        Kernel::setRedirect($this->getLink('users/'));
        if ($this->checkRights('Users', 'delete users')) {
            $user = $this->usersRecord;
            $user['data'] = array('id' => (int) $_GET['url']);
            if (!$this->dbapi->refresh($user)) {
                Modules::getModule('View')->addMessage(
                        $this->lang('userNotExists'), View::MSG_ERROR);
                return $result;
            }
            if (($user['data']['login'] == 'root') ||
                    ($user['data']['login']) == '<guest>') {
                Modules::getModule('View')->addMessage(
                        $this->lang('cannotDeleteRoot'), View::MSG_ERROR);
                return $result;
            }
            $this->deleteUserMetadata($user);
            $result = $this->dbapi->delete($user);
            Modules::getModule('View')->addMessage($this->lang($result ?
                    'userDeleted' : 'userNotDeleted'), $result ?
                    View::MSG_NOTICE : View::MSG_ERROR);
        } else {
            Modules::getModule('View')->addMessage(
                    $this->lang('notSufficentRights'), View::MSG_ERROR);
        }
        return $result;
    }

    public function &onAddUser(&$details, $source) {
        $result = null;
        Kernel::setRedirect($this->getLink('users/'));
        if ($this->checkRights('Users', 'create user')) {
            if ($_POST['password'] != $_POST['password2']) {
                Kernel::setRedirect($this->getLink('add-user/'));
                Modules::getModule('View')->addMessage(
                        $this->lang('passwordsNotSame'), View::MSG_ERROR);
                return $result;
            }
            $check = &$this->dbapi->load($this->usersRecord, '`login` = \'' .
                    $_POST['login'] . '\'');
            if (count($check) > 0) {
                Kernel::setRedirect($this->getLink('add-user/'));
                Modules::getModule('View')->addMessage(
                        $this->lang('loginUsed'), View::MSG_ERROR);
                return $result;
            }
            $user = $this->usersRecord;
            $result = $this->saveNewUser($user);
            Modules::getModule('View')->addMessage($this->lang($result ?
                    'userCreated' : 'userNotCreated'), $result ?
                    View::MSG_NOTICE : View::MSG_ERROR);
            if (!$result) {
                Kernel::setRedirect($this->getLink('add-user/'));
            }
            $this->saveNewUserRights($user);
            $this->saveNewUserGroups($details, $user['data']['id']);
        } else {
            Modules::getModule('View')->addMessage(
                    $this->lang('notSufficentRights'), View::MSG_ERROR);
        }
        return $result;
    }

    public function &onEditUser(&$details, $source) {
        Kernel::setRedirect($this->getLink('users/'));
        $result = null;
        $currentUser = &$this->getUser();
        if ($this->checkRights('Users', 'edit users') ||
                ($currentUser['data']['id'] == (int) $details['userId'])) {
            $user = $this->usersRecord;
            $user['data'] = array('id' => (int) $details['userId']);
            $this->dbapi->refresh($user);
            $user['data']['name'] = $details['name'];
            $user['data']['surname'] = $details['surname'];
            $user['data']['email'] = $details['email'];
            $user['data']['www'] = $details['www'];
            $files = Modules::getModule('Files')->uploadFiles($_FILES, 1);
            if (!empty($files)) {
                $user['data']['photo'] = $files[0]['data']['id'];
            }
            if ($details['password'] != '') {
                $this->changePassword($user, $details);
            }
            $this->changeUserRights($user['data']['id'], $details);
            $this->dbapi->update($user);
            $this->editUsersGroups($details, $user['data']['id']);
        } else {
            Modules::getModule('View')->addMessage(
                    $this->lang('notSufficentRights'), View::MSG_ERROR);
        }
        return $result;
    }

    public function &onAddGroup(&$details, $source) {
        Kernel::setRedirect($this->getLink('groups/'));
        $result = null;
        if (!$this->checkRights('Users', 'create groups')) {
            Modules::getModule('View')->addMessage(
                    $this->lang('notSufficentRights'), View::MSG_ERROR);
            return $result;
        }
        list($module, $id) = split('-', $details['requires'], 2);
        if (!$this->checkRights($module, $id)) {
            Modules::getModule('View')->addMessage(
                    $this->lang('notSufficentRightsForGroupRequired'),
                    View::MSG_ERROR);
            return $result;
        }
        $group = $this->groupsRecord;
        $group['data'] = array('name' => $details['name'], 'require' =>
                $details['requires']);
        $this->dbapi->save($group);
        if (!$this->saveGroupRights($details, $group['data']['id'])) {
            Modules::getModule('View')->addMessage(
                    $this->lang('notSufficentRightsSetGroupRights'),
                    View::MSG_WARNING);
        }
        return $result;
    }

    public function &onEditGroup(&$details, $source) {
        Kernel::setRedirect($this->getLink('groups/'));
        $result = null;
        if (!$this->checkRights('Users', 'edit groups')) {
            Modules::getModule('View')->addMessage(
                    $this->lang('notSufficentRights'), View::MSG_ERROR);
            return $result;
        }
        $group = $this->groupsRecord;
        $group['data'] = array('id' => (int) $details['groupId']);
        $this->dbapi->refresh($group);
        $group['data']['name'] = $details['name'];
        list($module, $id) = split('-', $details['requires'], 2);
        if ($details['requires'] != $group['data']['require']) {
            if ($this->canAssignRight($module, $id)) {
                $group['data']['require'] = $details['requires'];
            } else {
                Modules::getModule('View')->addMessage(
                        $this->lang('notSufficentRightsForGroupRequired'),
                        View::MSG_WARNING);
            }
        }
        $this->dbapi->update($group);
        $this->updateGroupRights($details, $group['data']['id']);
        return $result;
    }

    public function &onReloadRightsList(&$details, $source) {
        $result = null;
        Kernel::setRedirect($this->getLink());
        //if (!$this->hasRights('reload rights')) {
        //    Modules::getModule('View')->addMessage($this->lang(
        //            'notSufficentRights'), View::MSG_ERROR);
        //    return $result;
        //}
        $this->dbdriver->delete(self::RIGHTS_TABLE);
        $modules = Modules::getModuleList();
        foreach ($modules as $module) {
            $moduleInstance = Modules::getModule($module);
            if ($moduleInstance != null) {
                $this->registerRights($module, $moduleInstance->getRights());
            }
        }
        return $result;
    }

    /**
     * Performs safer logging in.
     *
     */
    private function safeLoginUser() {
        if ($_POST['sendTimestamp'] < $_POST['timestamp']) {
            return;
        }
        if ((int) $_POST['sendTimestamp'] < time() - $this->loginTimeout) {
           return;
        }
        if ((int) $_POST['timestamp'] < time() - $this->logoutTimeout) {
            return;
        }
        $user = &$this->dbapi->load($this->usersRecord, "`login` = '" .
                $this->dbdriver->escapeString($_POST['login']) . "' AND " .
                "`active` > 0");
        if (count($user) == 0) {
            return;
        }
        $check = sha1($_POST['sendTimestamp'] . $user[0]['data']['password']);
        if ($check != $_POST['password']) {
            return;
        }
        $user[0]['data']['lastLogin'] = time();
        $this->dbapi->update($user[0]);
        $_SESSION['user'] = $user[0];
    }

    /**
     * Updates rights of the group.
     *
     * @param Array $details Event editGroup details.
     * @param int $groupId Group ID number.
     */
    private function updateGroupRights(&$details, $groupId) {
        $ownedRights = &$this->dbapi->load($this->groupRightsRecord,
                '`group` = ' . $groupId);
        foreach ($ownedRights as $ownedRight) {
            $keep = false;
            if (isset($details['rights']) && is_array($details['rights'])) {
                foreach ($details['rights'] as $right) {
                    list($module, $id) = split('-', $right, 2);
                    if (($ownedRight['data']['module'] == $module) &&
                            ($ownedRight['data']['right'] == $id)) {
                        $keep = true;
                    }
                }
            }
            if (!$keep) {
                if ($this->canAssignRight($ownedRight['data']['module'],
                        $ownedRight['data']['right'])) {
                    $this->dbapi->delete($ownedRight);
                } else {
                    Modules::getModule('View')->addMessage($this->lang(
                            'notSufficentRightsRemoveRightFromGroup'),
                            View::MSG_WARNING);
                }
            }
        }
        if (isset($details['rights']) && is_array($details['rights'])) {
            foreach ($details['rights'] as $right) {
                $owned = false;
                list($module, $id) = split('-', $right, 2);
                foreach ($ownedRights as $ownedRight) {
                    if (($ownedRight['data']['module'] == $module) &&
                            ($ownedRight['data']['right'] == $id)){
                        $owned = true;
                    }
                }
                if (!$owned) {
                    if ($this->canAssignRight($module, $id)) {
                        $newRight = $this->groupRightsRecord;
                        $newRight['data'] = array('group' => $groupId,
                                'module' => $module, 'right' => $id);
                        $this->dbapi->save($newRight);
                    } else {
                        Modules::getModule('View')->addMessage($this->lang(
                                'notSufficentRightsAddRightToGroup'),
                                View::MSG_WARNING);
                    }
                }
            }
        }
    }

    /**
     * Displays administration interface for editting user groups.
     *
     */
    private function displayAdminEditGroup() {
        if (!$this->checkRights('Users', 'edit groups')) {
            return;
        }
        $details = Modules::getModule('View')->getUrl();
        $group = $this->groupsRecord;
        $group['data'] = array('id' => (int) $details[2]);
        $this->dbapi->refresh($group);
        $params = array('form' => $this->getForm('editGroup', true, 'Users'),
                'groupId' => $group['data']['id'], 'editGroup' =>
                $this->lang('editGroupHead'), 'rightsLbl' =>
                $this->lang('rights'), 'name' => $this->lang('groupName'),
                'requiredForAssignment' =>
                $this->lang('requiredForAssignment'), 'save' =>
                $this->lang('save'), 'groupName' => $group['data']['name']);
        $params['rights'] = &$this->loadRights();
        $this->highlightRequiredRight($params['rights'], $group);
        $this->highlightOwnedGroupRights($params['rights'], $group);
        $this->template('editgroup', $params);
    }

    /**
     * Marks rights that are owned by the grop.
     *
     * @param Array $rights Rights.
     * @param Array $groupId Group.
     */
    private function highlightOwnedGroupRights(&$rights, &$group) {
        foreach ($rights as &$right) {
            $check = &$this->dbapi->load($this->groupRightsRecord, '`group` ' .
                    '= ' . $group['data']['id'] . ' AND `module` = \'' .
                    $this->dbdriver->escapeString($right['mod']) . '\' ' .
                    'AND `right` = \'' .
                    $this->dbdriver->escapeString($right['id']) . '\'');
            $right['owned'] = count($check) > 0;
        }
    }

    /**
     * Marks right that is required for user to enter the group.
     *
     * @param Array $rights User rights.
     * @param Array $group Group of users - record.
     */
    private function highlightRequiredRight(&$rights, &$group) {
        list($module, $id) = split('-', $group['data']['require'], 2);
        foreach ($rights as &$right) {
            $right['required'] = ($right['mod'] == $module) &&
                    ($right['id'] == $id);
        }
    }

    /**
     * Adds new groups for edited user.
     *
     * @param Array $ownedGroups Records of groups of which the user is member.
     * @param Array $details Event editUser details.
     * @param int $userId ID number of user.
     */
    private function editUsersAddGroups(&$ownedGroups, &$details, $userId) {
        if (isset($details['groups']) && is_array($details['groups'])) {
            foreach ($details['groups'] as $group) {
                $owned = false;
                foreach ($ownedGroups as $ownedGroup) {
                    if ($ownedGroup['data']['group'] == $group) {
                        $owned = true;
                    }
                }
                if (!$owned) {
                    if ($this->checkRights('Users', 'add user to group')) {
                        if ($this->canAssignGroup($group)) {
                            $groupRecord = $this->usersInGroupRecord;
                            $groupRecord['data'] = array('group' => $group,
                                    'user' => $userId);
                            $this->dbapi->save($groupRecord);
                        } else {
                            Modules::getModule('View')->addMessage($this->lang(
                                    'notSufficentRightsAddUserToSomeGroups'),
                                    View::MSG_WARNING);
                        }
                    } else {
                        Modules::getModule('View')->addMessage(
                            $this->lang('notSufficentRightsAddUserToGroup'),
                            View::MSG_WARNING);
                    }
                }
            }
        }
    }

    /**
     * Performs changes in user's group membership.
     *
     * @param Array $details Event details.
     * @param int $userId User ID number.
     */
    private function editUsersGroups(&$details, $userId) {
        $ownedGroups = &$this->dbapi->load($this->usersInGroupRecord,
                '`user` = ' . $userId);
        foreach ($ownedGroups as $ownedGroup) {
            $keep = false;
            if (isset($details['groups']) && is_array($details['groups'])) {
                foreach ($details['groups'] as $group) {
                    if ($ownedGroup['data']['group'] == $group) {
                        $keep = true;
                    }
                }
            }
            if (!$keep) {
                if ($this->checkRights('Users', 'remove user from group')) {
                    if ($this->canAssignGroup($ownedGroup['data']['group'])) {
                        $this->dbapi->delete($ownedGroup);
                    } else {
                        Modules::getModule('View')->addMessage($this->lang(
                                'notSufficentRightsRemoveSomeFromGroup'),
                                View::MSG_WARNING);
                    }
                } else {
                    Modules::getModule('View')->addMessage(
                            $this->lang('notSufficentRightsRemoveFromGroup'),
                            View::MSG_WARNING);
                }
            }
        }
        $this->editUsersAddGroups($ownedGroups, $details, $userId);
    }

    /**
     * Saves group memebership for a new user.
     *
     * @param Array $details Event details.
     * @param int $userId New user ID number.
     */
    private function saveNewUserGroups(&$details, $userId) {
        if (isset($details['groups']) && is_array($details['groups']) &&
                (count($details['groups']) > 0)) {
            if (!$this->checkRights('Users', 'add user to group')) {
                Modules::getModule('View')->addMessage(
                        $this->lang('notSufficentRightsAddUserToGroup'),
                        View::MSG_WARNING);
                return;
            }
            foreach ($details['groups'] as $group) {
                if ($this->canAssignGroup($group)) {
                    $userInGroup = $this->usersInGroupRecord;
                    $userInGroup['data'] = array('user' => $userId,
                            'group' => $group);
                    $this->dbapi->save($userInGroup);
                } else {
                    Modules::getModule('View')->addMessage($this->lang('not' .
                            'SufficentRightsAddUserToSomeGroups'),
                            View::MSG_WARNING);
                }
            }
        }
    }

    /**
     * Checks whether current user can add user to specified group.
     *
     * @param int $groupId ID number of group.
     */
    private function canAssignGroup($groupId) {
        $group = $this->groupsRecord;
        $group['data']['id'] = $groupId;
        $this->dbapi->refresh($group);
        list($module, $id) = split('-', $group['data']['require'], 2);
        return $this->checkRights($module, $id);
    }

    /**
     * Saves rights of new group.
     *
     * @param Array $details Event details.
     * @param int $groupId Group ID number.
     * @return boolean True on success, false if some rights are not satisfied.
     */
    private function saveGroupRights(&$details, $groupId) {
        $result = true;
        if (is_array($details['rights'])) {
            foreach ($details['rights'] as $right) {
                list($module, $id) = split('-', $right, 2);
                if ($this->canAssignRight($module, $id)) {
                    $right = $this->groupRightsRecord;
                    $right['data'] = array('group' => $groupId, 'module' =>
                            $module, 'right' => $id);
                    $this->dbapi->save($right);
                }
            }
        }
        return $result;
    }

    /**
     * Displays administration interface for adding new group.
     *
     */
    private function displayAdminAddGroup() {
        if (!$this->checkRights('Users', 'create groups')) {
            return;
        }
        $params = array('addGroup' => $this->lang('addGroupHead'),
                'rightsLbl' => $this->lang('rights'), 'name' =>
                $this->lang('groupName'), 'requiredForAssignment' =>
                $this->lang('requiredForAssignment'), 'create' =>
                $this->lang('create'), 'form' => $this->getForm('addGroup',
                true, 'Users'));
        $params['rights'] = &$this->loadRights();
        $this->template('addgroup', $params);
    }

    /**
     * Displays administration intergace for groups.
     *
     */
    private function displayAdminGroups() {
        if (!$this->checkRights('Users', 'list groups')) {
            return;
        }
        $groups = &$this->dbapi->load($this->groupsRecord);
        foreach ($groups as &$group) {
            $group = $group['data'];
            $group['name'] = htmlspecialchars($group['name']);
            $group['edit'] = $this->getLink("edit-group/{$group['id']}/");
            $group['delete'] = $this->getLink($group['id'] . '/',
                    'deleteGroup');
        }
        $params = array('groupsLbl' => $this->lang('groups'), 'options' =>
                $this->lang('optionsHead'), 'groups' => $groups, 'edit' =>
                $this->lang('edit'), 'delete' => $this->lang('delete'));
        $this->template('groups', $params);
    }

    /**
     * Changes user rights when edditing a user.
     *
     * @param int $userId User ID number.
     * @param Array $details Event editUser details.
     */
    private function changeUserRights($userId, &$details) {
        $this->changeUserOwnedRights($userId, $details);
        $this->changeUserRevokedRights($userId, $details);
    }

    /**
     * Changes owned user rights when edditing a user.
     *
     * @param int $userId User ID number.
     * @param Array $details Event editUser details.
     */
    private function changeUserRevokedRights($userId, &$details) {
        $revokedRights = &$this->dbapi->load($this->userRevokedRecord,
                '`user` = ' . $userId);
        foreach ($revokedRights as $revokedRight) {
            $keep = false;
            if (isset($details['revokedRights']) &&
                    is_array($details['revokedRights'])) {
                foreach ($details['revokedRights'] as $right) {
                    list($module, $id) = split('-', $right, 2);
                    if (($revokedRight['data']['module'] == $module) &&
                            ($revokedRight['data']['right'] == $id)) {
                        $keep = true;
                    }
                }
            }
            if (!$keep && $this->canAssignRight(
                    $revokedRight['data']['module'],
                    $revokedRight['data']['right'])) {
                $this->dbapi->delete($revokedRight);
            }
        }
        if (isset($details['revokedRights']) &&
                is_array($details['revokedRights'])) {
            foreach ($details['revokedRights'] as $right) {
                list($module, $id) = split('-', $right, 2);
                $owned = false;
                foreach ($revokedRights as $revokedRight) {
                    if (($revokedRight['data']['module'] == $module) &&
                            ($revokedRight['data']['right'] == $id)) {
                        $owned = true;
                    }
                }
                if (!$owned && $this->canAssignRight($module, $id)) {
                    $right = $this->userRevokedRecord;
                    $right['data'] = array('user' => $userId, 'module' =>
                            $module, 'right' => $id);
                    $this->dbapi->save($right);
                }
            }
        }
    }

    /**
     * Changes owned user rights when edditing a user.
     *
     * @param int $userId User ID number.
     * @param Array $details Event editUser details.
     */
    private function changeUserOwnedRights($userId, &$details) {
        $ownedRights = &$this->dbapi->load($this->userRightsRecord, '`user` ' .
                '= ' . $userId);
        foreach ($ownedRights as $ownedRight) {
            $keep = false;
            if (isset($details['rights']) && is_array($details['rights'])) {
                foreach ($details['rights'] as $right) {
                    list($module, $id) = split('-', $right, 2);
                    if (($ownedRight['data']['module'] == $module) &&
                            ($ownedRight['data']['right'] == $id)) {
                        $keep = true;
                    }
                }
            }
            if (!$keep && $this->canAssignRight($ownedRight['data']['module'],
                    $ownedRight['data']['right'])) {
                $this->dbapi->delete($ownedRight);
            }
        }
        if (isset($details['rights']) && is_array($details['rights'])) {
            foreach ($details['rights'] as $right) {
                list($module, $id) = explode('-', $right, 2);
                $owned = false;
                foreach ($ownedRights as $ownedRight) {
                    if (($ownedRight['data']['module'] == $module) &&
                            ($ownedRight['data']['right'] == $id)) {
                        $owned = true;
                    }
                }
                if (!$owned && $this->canAssignRight($module, $id)) {
                    $right = $this->userRightsRecord;
                    $right['data'] = array('user' => $userId, 'module' =>
                            $module, 'right' => $id);
                    $this->dbapi->save($right);
                }
            }
        }
    }

    /**
     * Changes password of a user.
     *
     * @param Array $user User record.
     * @param Array $details Data for event editUser.
     */
    private function changePassword(&$user, &$details) {
        if ($this->checkRights('Users', 'assign new password') ||
                ($user['data']['id'] == (int) $details['userId'])) {
            if ($details['password'] == $details['password2']) {
                $user['data']['password'] = sha1($details['password']);
            } else {
                Modules::getModule('View')->addMessage(
                        $this->lang('passNotChangedEquals'),
                        View::MSG_WARNING);
            }
        } else {
            Modules::getModule('View')->addMessage(
                    $this->lang('passNotChangedRights'), View::MSG_WARNING);
        }
    }

    /**
     * Deletes user assigned rights, groups and revoked rights.
     *
     * @param Array $user User of which metadata should be deleted.
     */
    private function deleteUserMetadata(&$user) {
        $rights = &$this->dbapi->load($this->userRightsRecord, '`user` = ' .
                $user['data']['id']);
        foreach ($rights as $right) {
            if (!$this->dbapi->delete($right)) {
                Modules::getModule('View')->addMessage(
                        $this->lang('cannotUnassignRight') .
                        $right['data']['module'] . '-' .
                        $right['data']['right'], View::MSG_WARNING);
            }
        }
        $rights = &$this->dbapi->load($this->userRevokedRecord, '`user` = ' .
                $user['data']['id']);
        foreach ($rights as $right) {
            if (!$this->dbapi->delete($right)) {
                Modules::getModule('View')->addMessage(
                        $this->lang('cannotUnassignRight') .
                        $right['data']['module'] . '-' .
                        $right['data']['right'], View::MSG_WARNING);
            }
        }
        $groups = &$this->dbapi->load($this->usersInGroupRecord, '`user` = ' .
                $user['data']['id']);
        foreach ($groups as $group) {
            if (!$this->dbapi->delete($group)) {
                odules::getModule('View')->addMessage(
                        $this->lang('cannotUnassignGroup') .
                        $right['data']['module'] . $group['data']['group'],
                        View::MSG_WARNING);
            }
        }
    }

    /**
     * Saves rights of new user.
     *
     * @param Array $user User record.
     */
    private function saveNewUserRights(&$user) {
        $result = true;
        if (isset($_POST['rights'])) {
            foreach ($_POST['rights'] as $rightInput) {
                list($module, $id) = split('-', $rightInput, 2);
                $right = $this->userRightsRecord;
                $right['data'] = array('user' => $user['data']['id'], 'module' =>
                        $module, 'right' => $id);
                if (!$this->canAssignRight($module, $id) ||
                        !$this->dbapi->save($right)) {
                    $result = false;
                }
            }
        }
        if (isset($_POST['revokedRights'])) {
            foreach ($_POST['revokedRights'] as $rightInput) {
                list($module, $id) = split('-', $rightInput, 2);
                $right = $this->userRevokedRecord;
                $right['data'] = array('user' => $user['data']['id'], 'module' =>
                        $module, 'right' => $id);
                if (!$this->canAssignRight($module, $id) ||
                        !$this->dbapi->save($right)) {
                    $result = false;
                }
            }
        }
        if (!$result) {
            Modules::getModule('View')->addMessage(
                    $this->lang('cannotSaveRights'), View::MSG_WARNING);
        }
    }

    /**
     * Check whether user has right to assign right to another user.
     *
     * @param String $module Module of which right is about to be assigned.
     * @param String $id Id of right to assign.
     * @return boolean True if current user is allowed to assign this right to
     *         another user.
     */
    private function canAssignRight($module, $id) {
        $right = &$this->dbapi->load($this->rightsRecord, '`module` = \'' .
                $this->dbdriver->escapeString($module) . '\' AND `id` = \'' .
                $this->dbdriver->escapeString($id) . '\'');
        if (count($right) == 0) {
            return false;
        }
        if (strpos($right[0]['data']['requires'], '-') !== false) {
            list($module, $id) = split('-', $right[0]['data']['requires']);
        } else {
            $module = 'Users';
            $id = $right[0]['data']['requires'];
        }
        $result = $this->checkRights($module, $id);
        if (!$result) {
            Modules::getModule('View')->addMessage(
                    $this->lang('cannotAssignRight') . $module . '-' . $id,
                    View::MSG_WARNING);
        }
        return $result;
    }

    /**
     * Saves new user from POST data.
     *
     * @param Array $user Empty user record.
     * @return boolean True on success, false otherwise
     */
    private function saveNewUser(&$user) {
        $user['data'] = $_POST;
        $user['data']['registered'] = time();
        $user['data']['active'] = 1;
        $user['data']['password'] = sha1($user['data']['password']);
        return $this->dbapi->save($user);
    }

    /**
     * Displays administration interface
     *
     * @param mixed $param View parameter.
     */
    private function displayAdmin($param) {
        if (!$this->checkRights('Users', '_view admin')) {
            if ($param == '') {
                $this->displayAdminLoginForm();
            }
            return;
        }
        if (!$this->checkRights('Users', 'view admin')) {
            return;
        }
        switch ($param) {
            case 'submenu':
                $this->displayAdminSubmenu();
                break;
            case 'logout':
                $user = &$this->getUser();
                $params = array('link' => $this->getLink('', 'logout'),
                        'logoutTitle' => $this->lang('logoutInfo'), 'logout' =>
                        $this->lang('logout'), 'user' =>
                        $user['data']['login']);
                $this->template('logout', $params);
                break;
            default:
                $details = Modules::getModule('View')->getUrl();
                if (count($details) > 1) {
                    switch ($details[1]) {
                        case 'users':
                            $this->displayAdminUsers();
                            break;
                        case 'add-user':
                            $this->displayAdminAddUser();
                            break;
                        case 'edit-user':
                            $this->displayAdminEditUser();
                            break;
                        case 'groups':
                            $this->displayAdminGroups();
                            break;
                        case 'add-group':
                            $this->displayAdminAddGroup();
                            break;
                        case 'edit-group':
                            $this->displayAdminEditGroup();
                            break;
                    }
                } else {
                    $this->displayAdminLoggedUser();
                }
                break;
        }
    }

    /**
     * Displays user edditing interface.
     *
     */
    private function displayAdminEditUser() {
        $currentUser = &$this->getUser();
        $urlDetails = Modules::getModule('View')->getUrl();
        if (!$this->checkRights('Users', 'edit users') &&
                ($currentUser['data']['id'] != (int) $urlDetails[2])) {
            return;
        }
        $user = $this->usersRecord;
        $user['data'] = array('id' => (int) $urlDetails[2]);
        $this->dbapi->refresh($user);
        $params = array('editUserForm' => $this->lang('editUserForm'),
                'groupsLbl' => $this->lang('groups'), 'rightsLbl' =>
                $this->lang('rights'), 'revokedRights' =>
                $this->lang('revokedRights'), 'login' => $this->lang('login'),
                'password' => $this->lang('password'), 'retypePassword' =>
                $this->lang('retypePassword'), 'photo' => $this->lang('photo'),
                'name' => $this->lang('name'), 'surname' =>
                $this->lang('surname'), 'email' => $this->lang('email'),
                'www' => $this->lang('www'), 'save' =>
                $this->lang('save'), 'formStart' => $this->getForm(
                'editUser', true, 'Users'), 'keepPasswordEmpty' =>
                $this->lang('keepPasswordEmpty'), 'uLogin' =>
                $user['data']['login'], 'uSurname' => $user['data']['surname'],
                'uName' => $user['data']['name'], 'uEmail' =>
                $user['data']['email'], 'uWWW' => $user['data']['www'],
                'userId' => $user['data']['id']);
        $params['groups'] = &$this->dbapi->load($this->groupsRecord);
        foreach ($params['groups'] as &$group) {
            $group = $group['data'];
        }
        $params['rights'] = &$this->loadRights();
        $this->highlightOwnedGroups($params['groups'], $user['data']['id']);
        $this->highlightOwnedRights($params['rights'], $user['data']['id']);
        $this->highlightRevokedRights($params['rights'], $user['data']['id']);
        $this->template('edituser', $params);
    }

    private function highlightOwnedGroups(&$groups, $userId) {
        foreach ($groups as &$group) {
            $check = &$this->dbapi->load($this->usersInGroupRecord, '`user` ' .
                    '= ' . $userId . ' AND `group` = ' . $group['id']);
            $group['owned'] = count($check) > 0;
        }
    }

    /**
     * Highlights all rights that are revoked for user.
     *
     * @param Array $rights List of rights data extracted from records.
     * @param int $userId User ID number
     */
    private function highlightRevokedRights(&$rights, $userId) {
        foreach ($rights as &$right) {
            $check = &$this->dbapi->load($this->userRevokedRecord,
                    '`user` = ' . (int) $userId . ' AND `module` = \'' .
                    $this->dbdriver->escapeString($right['mod']) . '\' AND ' .
                    '`right` = \'' .
                    $this->dbdriver->escapeString($right['id']) . '\'');
            $right['revoked'] = count($check) > 0;
        }
    }

    /**
     * Highlights all rights that user owns.
     *
     * @param Array $rights Array of rights data extracted from records.
     * @param int $userId User ID number
     */
    private function highlightOwnedRights(&$rights, $userId) {
        foreach ($rights as &$right) {
            $check = &$this->dbapi->load($this->userRightsRecord, '`user` = ' .
                    (int) $userId . ' AND `module` = \'' .
                    $this->dbdriver->escapeString($right['mod']) . '\' AND ' .
                    '`right` = \'' .
                    $this->dbdriver->escapeString($right['id']) . '\'');
            $right['owned'] = count($check) > 0;
        }
    }

    /**
     * Display administration interface for addding new users.
     *
     */
    private function displayAdminAddUser() {
        if (!$this->checkRights('Users', 'create user')) {
            return;
        }
        $params = array('addUserForm' => $this->lang('addUserForm'),
                'groupsLbl' => $this->lang('groups'), 'rightsLbl' =>
                $this->lang('rights'), 'revokedRights' =>
                $this->lang('revokedRights'), 'login' => $this->lang('login'),
                'password' => $this->lang('password'), 'retypePassword' =>
                $this->lang('retypePassword'), 'photo' => $this->lang('photo'),
                'name' => $this->lang('name'), 'surname' =>
                $this->lang('surname'), 'email' => $this->lang('email'),
                'www' => $this->lang('www'), 'create' =>
                $this->lang('create'), 'formStart' => $this->getForm('addUser',
                true, 'Users'));
        $params['groups'] = &$this->dbapi->load($this->groupsRecord);
        foreach ($params['groups'] as &$group) {
            $group = $group['data'];
        }
        $params['rights'] = &$this->loadRights();
        $this->template('adduser', $params);
    }

    /**
     * Loads rights for displaying in UI.
     *
     * @return Array User rights
     */
    private function &loadRights() {
        $rights = &$this->dbapi->load($this->rightsRecord);
        foreach ($rights as &$right) {
            $right = $right['data'];
            $right['mod'] = $right['module'];
            if (Modules::getModule($right['mod']) != false) {
                $right['module'] = Modules::getModule($right['mod'])->
                        getUIName();
                $details = Modules::getModule($right['mod'])->
                        getRightLocalization($right['id']);
                $right['name'] = $details['name'];
                $right['description'] = $details['description'];
            } else {
                $right['module'] = $right['mod'];
                $right['name'] = $right['id'];
            }
        }
        return $rights;
    }

    /**
     * Displays administration of users catalogue.
     *
     */
    private function displayAdminUsers() {
        if (!$this->checkRights('Users', 'list users')) {
            return;
        }
        $users = &$this->dbapi->load($this->usersRecord);
        $params = array('head' => array(array($this->lang('loginHead'),
                $this->lang('nameHead'), $this->lang('surnameHead'),
                $this->lang('registeredHead'), $this->lang('lastLoginHead'),
                $this->lang('activeHead'), $this->lang('optionsHead'))));
        $listParameters = array('properties' => array('login', 'name',
                'surname', 'registered', 'lastLogin', 'active', 'id'));
        $params['items'] = &$this->recordList->getList($this->usersRecord,
                $listParameters);
        $this->parseUsersInfo($params['items']);
        $this->template('table', $params);
    }

    /**
     * Parses data in list of data extracted from user records.
     *
     * @param Array $users List of user records.
     */
    private function parseUsersInfo(&$users) {
        foreach ($users as &$user) {
            $user['login'] = str_replace('<', '&lt;',
                    str_replace('>', '&gt;', $user['login']));
            $user['registered'] = date("d.m.Y", $user['registered']);
            $user['lastLogin'] = (int) $user['lastLogin'] != 0 ?
                    date("d.m.Y", $user['lastLogin']) : '-';
            $user['active'] = $this->lang($user['active'] == 1 ? 'yes' :
                    'no');
            $user['id'] = '<a href="' .
                    $this->getLink("edit-user/{$user['id']}/") . '">' .
                    $this->lang('edit') . '</a> <a href="' .
                    $this->getLink($user['id'] . '/', 'deleteUser') . '">' .
                    $this->lang('delete') . '</a>';
            $user = array_values($user);
        }
    }

    /**
     * Sets error messages when user tries to perform a forbidden action.
     *
     */
    private function setAccessErrorMsgs() {
        if (Kernel::getMode() == Kernel::ADMIN) {
            $view = Modules::getModule('View');
            if ($view == null) {
                return;
            }
            $details = $view->getUrl();
            $right = null;
            if (count($details) > 1) {
                switch ($details[1]) {
                    case 'users':
                        $right = 'list users';
                        break;
                    case 'add-user':
                        $right = 'create user';
                        break;
                    case 'edit-user':
                        $user = &$this->getUser();
                        $urlDetails = Modules::getModule('View')->getUrl();
                        if ($user['data']['id'] != (int) $urlDetails[2]) {
                            $right = 'edit users';
                        }
                        break;
                    case 'groups':
                        $right = 'list groups';
                        break;
                    case 'add-group':
                        $right = 'create groups';
                        break;
                    case 'edit-group':
                        $right = 'edit groups';
                        break;
                }
                if (($right != null) && !$this->checkRights('Users', $right)) {
                            Modules::getModule('View')->addMessage(
                                    $this->lang('notSufficentRights'),
                                    View::MSG_ERROR);
                }
            }
        }
    }

    /**
     * Displays submenu for administration.
     *
     */
    private function displayAdminSubmenu() {
        $params = array('menu' => array(array('href' => $this->getLink(),
                'title' => $this->lang('loggedUserInfo'), 'label' =>
                $this->lang('loggedUser')), array('href' =>
                $this->getLink('users/'), 'title' => $this->lang('usersInfo'),
                'label' => $this->lang('users')), array('href' =>
                $this->getLink('add-user/'), 'title' =>
                $this->lang('addUserInfo'), 'label' => $this->lang('addUser')),
                array('href' => $this->getLink('groups/'), 'title' =>
                $this->lang('groupsInfo'), 'label' => $this->lang('groups')),
                array('href' => $this->getLink('add-group/'), 'title' =>
                $this->lang('addGroupInfo'), 'label' =>
                $this->lang('addGroup')), array('href' => $this->getLink('',
                'reloadRightsList'), 'title' => $this->lang(
                'reloadRightsTitle'), 'label' => $this->lang('reloadRights')),
                array('href' => $this->getLink('',
                'logout'), 'title' => $this->lang('logoutInfo'), 'label' =>
                $this->lang('logout'))));
        $this->template('submenu', $params);
    }

    /**
     * Displays info about currently logged in user.
     *
     */
    private function displayAdminLoggedUser() {
        $user = &$this->getUser();
        $params = $user['data'];
        $params['registered'] = date("d.m.Y", $params['registered']);
        $params['lastLogin'] = date("d.m.Y", $params['lastLogin']);
        $params['active'] = $this->lang($params['active'] ? 'activeUser' :
                'nonactiveUser');
        $params2 = array('nameLbl' => $this->lang('name'),
                'surnameLbl' => $this->lang('surname'), 'emailLbl' =>
                $this->lang('email'), 'wwwLbl' => $this->lang('www'),
                'registeredLbl' => $this->lang('registered'), 'lastLoginLbl' =>
                $this->lang('lastLogin'));
        $params = array_merge($params, $params2);
        $this->template('user', $params);
    }

    /**
     * Displays login form.
     *
     */
    private function displayAdminLoginForm() {
        $params = array('haveToLogin' => $this->lang('haveToLogin'),
                'loginToAdmin' => $this->lang('loginToAdmin'),
                'login' => $this->lang('login'), 'password' =>
                $this->lang('password'), 'loginBtn' =>
                $this->lang('loginBtn'), 'formStart' =>
                $this->getForm('login', true, 'Users'), 'timestamp' => time());
        $this->template('login', $params);
    }
}
?>
